#!/bin/sh
#
# The Open Source Unix Installer
#
# The MIT License
#
# Copyright 2011-2013 Andrey Pudov.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

# Changes the current directory to the scripts directory
cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# use Intel C Compiler for Linux
source /opt/intel/bin/iccvars.sh intel64

### CONFIGURATION BLOCK ###

CC=clang
HEADERS=`find "../include" -name "*.h" -printf "-I$PWD/%h\n" | uniq | tr '\n' ' '`
    HEADERS+=`pkg-config --cflags gtk+-2.0`
    HEADERS+=`find "../test" -name "*.h" -printf "-I$PWD/%h\n" | uniq | tr '\n' ' '`
SOURCES=`find "../src" -name "*.c" | sed "s/..\/src\/main.c/..\/test\/u_main.c/g"`
LIBRARIES=`pkg-config --libs gtk+-2.0`
    LIBRARIES+="-lutil"
CFLAGS="-c -g -fstack-protector-all -Wformat-security -fpie -D_FORTIFY_SOURCE=2 -D_POSIX_C_SOURCE=200809L -std=c99"
EXECUTABLE=u_installer

# sets compiler depend flags
if [ $CC == icc ]; then
    CFLAGS+=" -w2"
elif [ $CC == clang ]; then
    CFLAGS+=" -Wall"
else
    CFLAGS+=" -Wall"
fi

# -c			compile to object only, do not link
# -g			produce symbolic debug information in object files
# -Wall			enable all warnings
# -w2			control diagnostics (display remarks, warnings and errors)
# -fstack-protector-all enable stack overflow security checks including functions
# -Wformat-security
# -fpie			generate position independent code

OUTPUT_FILE=".build_state.csv"

### DECLARATION BLOCK ###

# declare a hash table to store a dates
# MODIFICATION_TABLE[file_name]=modification_date
declare -A MODIFICATION_TABLE

# returns true if file is changed, and false otherwise
# $1 - file name
is_modified() {
    local MODIFICATION_TIME=`stat -c %Y $1`
    
    # if file is not in the list (not null)
    if [ -z "${MODIFICATION_TABLE[$1]}" ]; then
	MODIFICATION_TABLE[$1]=$MODIFICATION_TIME
	return 1
    fi
    
    # if file is not changed
    if [ "${MODIFICATION_TABLE[$1]}" -eq $MODIFICATION_TIME ]; then
	return 0
    else
	# apply new modification date
	MODIFICATION_TABLE[$1]=$MODIFICATION_TIME
	return 1
    fi
}

################################################################################
### MAIN CODE BLOCK                                                         ####
################################################################################

# load the previous state (is exist)
if [ -e $OUTPUT_FILE ]; then
    # output file is exist

    for item in $("cat" $OUTPUT_FILE); do
	MODIFICATION_TABLE[${item#*:}]=${item%:*}
    done
fi

# u_main shall be recompiled at every time
# because it include inheritance of linked headers
MODIFICATION_TABLE["../test/u_main.c"]="0"

for file in $SOURCES; do    
    # if file has been changed
    if ! is_modified $file; then
	echo "compile $file"
	$CC $CFLAGS $HEADERS $file -o ../build/`echo "$file" | sed 's/.*\///' | sed 's/.c/.o/g'`
	
	# if compiling is failed
	if [ $? -ne 0 ]; then
	    echo -e "\033[31;5;148mBUILD FAILED\033[39m"
	    exit -1
	fi
    else 
	echo -e "compile $file \033[31;5;148m(skipped)\033[39m"
    fi
done

# linking object files
echo "linking..."
$CC $LIBRARIES `find ../build -name "*.o" | sed "s/..\/build\/main.o//g"` -o ../build/$EXECUTABLE
# if linking is failed
if [ $? -ne 0 ]; then
    echo -e "\033[31;5;148mBUILD FAILED\033[39m"
    exit -1
fi

# save the current state
echo "saving..."
rm -f $OUTPUT_FILE
for item in ${!MODIFICATION_TABLE[@]}; do
    echo "${MODIFICATION_TABLE[$item]}:$item" >> $OUTPUT_FILE
done
